package aom.ju.ss.utils

import android.app.Activity
import android.content.ContentUris
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.text.TextUtils
import androidx.fragment.app.Fragment
import aom.ju.ss.utils.BaseApplication
import java.io.*
import java.net.MalformedURLException
import java.net.URL
import java.text.DecimalFormat
import java.util.*


/*
 * Created by Administrator on 2017/1/1.
 */
object FileUtils {
    @JvmStatic
    val file = BaseApplication.getInstance().externalCacheDir

    @JvmStatic
    val filePath = BaseApplication.getInstance().externalCacheDir?.absolutePath


    /**
     * @return new File
     */
    @JvmStatic
    fun newPngFile(): File {
        return File(
            BaseApplication.getInstance().externalCacheDir,
            System.currentTimeMillis().toString() + ".png"
        )
    }

    /**
     * @return new File
     */
    @JvmStatic
    fun newApkFile(): File {
        return File(
            BaseApplication.getInstance().externalCacheDir,
            System.currentTimeMillis().toString() + ".apk"
        )
    }

    /**
     * @return new File
     */
    fun newFile(name: String): File {
        val f =
            File(BaseApplication.getInstance().externalCacheDir.toString() + "/" + System.currentTimeMillis() + "." + name)
        if (!f.parentFile.exists()) {
            f.parentFile.mkdirs()
        }
        return f
    }


    /**
     * @return new File
     */
    @JvmStatic
    fun newFileAN(name: String): File {
        val f = File(BaseApplication.getInstance().externalCacheDir.toString() + "/" + name)
        if (!f.parentFile.exists()) {
            f.parentFile.mkdirs()
        }
        return f
    }


    @JvmStatic
    fun saveBitmapFile(bitmap: Bitmap, newfiles: String?): File {
        val newfile = File(newfiles)
        try {
            val bos = BufferedOutputStream(FileOutputStream(newfile))
            try {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos)
            } catch (e: NullPointerException) {
                LogUtils.e("无法获取这张图片")
            }
            bos.flush()
            bos.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return newfile
    }

    fun saveBitmapFile(bitmap: Bitmap): File {
        val file = File(storagePath + "/" + System.currentTimeMillis() + ".png") //将要保存图片的路径
        try {
            val bos = BufferedOutputStream(FileOutputStream(file))
            try {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 70, bos)
            } catch (e: NullPointerException) {
                LogUtils.e("无法获取这张图片")
            }
            bos.flush()
            bos.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return file
    }

    @JvmStatic
    fun saveBitmapFiles(bitmap: Bitmap, NAME: String): File {
        val file = File("$storagePath/$NAME.png") //将要保存图片的路径
        try {
            val bos = BufferedOutputStream(FileOutputStream(file))
            try {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 70, bos)
            } catch (e: NullPointerException) {
                LogUtils.e("无法获取这张图片")
            }
            bos.flush()
            bos.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return file
    }

    private fun getSmallBitmap(filePath: String): Bitmap {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(filePath, options)
        options.inSampleSize = calculateInSampleSize(options, 0, 1080) //最大分辨率
        options.inJustDecodeBounds = false
        val bitmap = BitmapFactory.decodeFile(filePath, options)
        val file = File(filePath)
        LogUtils.e(file.name)
        file.delete()
        return bitmap
    }

    /**
     * Compress Picture Save to CacheCatalog
     * 压缩图片保存到缓存目录
     *
     * @return 压缩后的文件
     */
    @JvmStatic
    fun CPSCC(bitmapFile: String): File {
        return saveBitmapFile(getSmallBitmap(bitmapFile), bitmapFile)
    }

    /**
     * 计算压缩比例值(改进版 by touch_ping)
     *
     *
     * 原版2>4>8...倍压缩
     * 当前2>3>4...倍压缩
     *
     * @param options   解析图片的配置信息
     * @param reqWidth  所需图片压缩尺寸最小宽度O
     * @param reqHeight 所需图片压缩尺寸最小高度
     * @return
     */
    fun calculateInSampleSize(
        options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int
    ): Int {
        // Raw height and width of image
        val height = options.outHeight
        val width = options.outWidth
        var inSampleSize = 1
        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2
            while (halfHeight / inSampleSize > reqHeight
                && halfWidth / inSampleSize > reqWidth
            ) {
                inSampleSize *= 2
            }
        }
        return inSampleSize
    }

    /**
     * 小数的格式化
     */
    val FORMAT = DecimalFormat("####.##")
    val FORMAT_ONE = DecimalFormat("####.#")

    /**
     * 根据文件路径获取文件名称
     *
     * @param filePath
     * @return
     */
    fun getFileName(filePath: String): String {
        return if (TextUtils.isEmpty(filePath)) {
            ""
        } else filePath.substring(filePath.lastIndexOf(File.separator) + 1)
    }

    /**
     * 根据传入的byte数量转换为对应的byte, Kbyte, Mbyte, Gbyte单位的字符串
     *
     * @param size byte数量
     * @return
     */
    @JvmStatic
    fun getFileSize(size: Long): String {
        if (size < 0) { //小于0字节则返回0
            return "0B"
        }
        var value = 0.0
        return when {
            size / 1024 < 1 -> { //0 ` 1024 byte
                size.toString() + "B"
            }
            size / (1024 * 1024) < 1 -> { //0 ` 1024 kbyte
                value = size / 1024f.toDouble()
                FORMAT.format(value) + "KB"
            }
            size / (1024 * 1024 * 1024) < 1 -> {                  //0 ` 1024 mbyte
                value = size * 100 / (1024 * 1024) / 100f.toDouble()
                FORMAT.format(value) + "MB"
            }
            else -> {                  //0 ` 1024 mbyte
                value = size * 100L / (1024L * 1024L * 1024L) / 100f.toDouble()
                FORMAT.format(value) + "GB"
            }
        }
    }

    val storagePath: String
        get() {
            val PATH: String
            PATH = BaseApplication.getInstance().externalCacheDir!!.absolutePath
            return PATH
        }

    val storageVideoPath: File
        get() {
            val file =
                File(BaseApplication.getInstance().externalCacheDir!!.absolutePath + "/video")
            if (!file.exists()) {
                file.mkdir()
            }
            return file
        }

    val storagePublicVideoPath: File
        get() {
            val file = File(
                BaseApplication.getInstance().externalCacheDir!!.absolutePath
                        + "/PublicVideo"
            )
            if (!file.exists()) {
                file.mkdir()
            }
            return file
        }

    /**
     * 保存文本到本地文件
     *
     * @param content
     */
    @JvmStatic
      fun saveFile(content: String) {
        var fwriter: FileWriter? = null
        try {
            fwriter = FileWriter(newFile("txt"))
            fwriter.write(content)
        } catch (ex: IOException) {
            ex.printStackTrace()
        } finally {
            try {
                fwriter!!.flush()
                fwriter.close()
            } catch (ex: IOException) {
                ex.printStackTrace()
            }
        }
    }

    val storageAudioPath: File
        get() {
            val file = File(
                BaseApplication.getInstance().externalCacheDir!!.absolutePath
                        + "/Audio"
            )
            if (!file.exists()) {
                file.mkdir()
            }
            return file
        }

    fun isNull(f: File): Boolean {
        try {
            if (!f.isFile) {
                return true
            }
        } catch (e: Exception) {
            LogUtils.e("1111111" + e.message)
            return true
        }
        return false
    }

    fun delFile(path: String?): Boolean {
        var isDle = false
        val mFile = File(path)
        isDle = if (mFile.exists()) {
            mFile.delete()
        } else {
            true
        }
        return isDle
    }

    /**
     * @return new File
     */
    @JvmStatic
    val pngList: List<File>
        get() {
            val list: MutableList<File> = ArrayList()
            for (s in BaseApplication.getInstance().externalCacheDir!!.list()) {
                if (s.contains(".png")) {
                    list.add(File(BaseApplication.getInstance().externalCacheDir.toString() + "/" + s))
                }
            }
            return list
        }


    /**
     * 将String数据存为文件
     */
    fun getFileFromBytes(name: String): File? {
        val b = name.toByteArray()
        var stream: BufferedOutputStream? = null
        var file: File? = null
        try {
            file = newFile("txt")
            val fstream = FileOutputStream(file)
            stream = BufferedOutputStream(fstream)
            stream.write(b)
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            if (stream != null) {
                try {
                    stream.close()
                } catch (e1: IOException) {
                    e1.printStackTrace()
                }
            }
        }
        return file
    }


    fun File2byte(tradeFile: File?): ByteArray? {
        var buffer: ByteArray? = null
        try {
            val fis = FileInputStream(tradeFile)
            val bos = ByteArrayOutputStream()
            val b = ByteArray(1024)
            var n: Int
            while (fis.read(b).also { n = it } != -1) {
                bos.write(b, 0, n)
            }
            fis.close()
            bos.close()
            buffer = bos.toByteArray()
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return buffer
    }


    fun getFile(act: Activity, code: Int) {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.type = "*/*"//设置类型，我这里是任意类型，任意后缀的可以这样写。
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        act.startActivityForResult(intent, code)
    }

    fun getFile(act: Fragment, code: Int) {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.type = "*/*"//设置类型，我这里是任意类型，任意后缀的可以这样写。
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        act.startActivityForResult(intent, code)
    }


    /**
     * uri 转 filePath
     *
     * @param context
     * @param uri
     * @return
     */
    fun getPath(context: Context, uri: Uri): String? {
        val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                if ("primary".equals(type, ignoreCase = true)) {
                    return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                }

            } else if (isDownloadsDocument(uri)) {
                val id = DocumentsContract.getDocumentId(uri)
                val contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)
                )
                return getDataColumn(
                    context,
                    contentUri,
                    null,
                    null
                )
            } else if (isMediaDocument(uri)) {
                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":").toTypedArray()
                val type = split[0]
                var contentUri: Uri? = null
                if ("image" == type) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                } else if ("video" == type) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                } else if ("audio" == type) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }
                val selection = "_id=?"
                val selectionArgs = arrayOf(
                    split[1]
                )
                return getDataColumn(
                    context,
                    contentUri,
                    selection,
                    selectionArgs
                )
            }
        } else if ("content".equals(uri.scheme, ignoreCase = true)) {
            return getDataColumn(context, uri, null, null)
        } else if ("file".equals(uri.scheme, ignoreCase = true)) {
            return uri.path
        }
        return null
    }


    fun getDataColumn(
        context: Context, uri: Uri?, selection: String?,
        selectionArgs: Array<String>?
    ): String? {
        var cursor: Cursor? = null
        val column = "_data"
        val projection = arrayOf(
            column
        )
        try {
            cursor = context.contentResolver.query(
                uri!!, projection, selection, selectionArgs,
                null
            )
            if (cursor != null && cursor.moveToFirst()) {
                val column_index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(column_index)
            }
        } finally {
            cursor?.close()
        }
        return null
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }

    interface callBackLp {
        fun ok(bt: ByteArray)
    }

    fun urlTobyte(url: String, callback: callBackLp) {
        try {
            val ur = URL(url)
            var ins: BufferedInputStream? = null
            var out: ByteArrayOutputStream? = null
            try {
                ins = BufferedInputStream(ur.openStream())
                out = ByteArrayOutputStream(1024)
                val temp = ByteArray(1024)
                var size = 0
                while (ins.read(temp).also { size = it } != -1) {
                    out.write(temp, 0, size)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                try {
                    ins?.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
            out?.toByteArray()?.let { callback.ok(it) }
        } catch (e: MalformedURLException) {
            e.printStackTrace()
        }
    }
}